#include <jni.h>
#include <string>
//ncnn
#include "Coor.h"
#include <android/log.h>
#include <android/bitmap.h>
using namespace std;
static Coor *coor;
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)

//sdk是否初始化成功
bool detection_sdk_init_ok = false;

#define TAG "OOR"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)


extern "C" JNIEXPORT jstring JNICALL
Java_bistu_grobot_oor_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
extern "C" JNIEXPORT jboolean  JNICALL
Java_bistu_grobot_oor_MainActivity_CoorModelInit(JNIEnv *env, jobject instance,jstring ModelPath_) {
    LOGD("JNI开始海洋生物识别模型初始化");
    //如果已初始化则直接返回
    if (detection_sdk_init_ok) {
        //  LOGD("人脸检测模型已经导入");
        return true;
    }
    jboolean tRet = false;
    if (NULL == ModelPath_) {
        //   LOGD("导入的人脸检测的目录为空");
        return tRet;
    }

    //获取模型的绝对路径的目录（不是/aaa/bbb.bin这样的路径，是/aaa/)
    const char *ModelPath = env->GetStringUTFChars(ModelPath_, 0);
    if (NULL == ModelPath) {
        return tRet;
    }

    string tModelDir = ModelPath;
    string tLastChar = tModelDir.substr(tModelDir.length() - 1, 1);
    //LOGD("init, tFaceModelDir last =%s", tLastChar.c_str());
    //目录补齐/
    if ("\\" == tLastChar) {
        tModelDir = tModelDir.substr(0, tModelDir.length() - 1) + "/";
    } else if (tLastChar != "/") {
        tModelDir += "/";
    }
    string::size_type pos=0;
    while((pos=tModelDir.find_first_of('\\',pos))!=string::npos)
    {
        tModelDir.insert(pos,"\\");//插入
        pos=pos+2;
    }
    //没判断是否正确导入，懒得改了
    LOGD("init, tModelDir=%s", tModelDir.c_str());
    coor = new Coor(tModelDir);
    coor->SetInputSize(416);
    env->ReleaseStringUTFChars(ModelPath_, ModelPath);
    detection_sdk_init_ok = true;
    tRet = true;
    return tRet;
}
extern "C" JNIEXPORT jfloatArray  JNICALL
Java_bistu_grobot_oor_MainActivity_CoorDetect(JNIEnv *env, jobject instance, jbyteArray imageDate_,
                                              jint imageWidth, jint imageHeight, jint imageChannel) {
    //  LOGD("JNI开始检测人脸");
    if(!detection_sdk_init_ok){
        LOGD("检测模型SDK未初始化，直接返回空");
        return NULL;
    }

    int tImageDateLen = env->GetArrayLength(imageDate_);
    if(imageChannel == tImageDateLen / imageWidth / imageHeight){
        LOGD("数据宽=%d,高=%d,通道=%d",imageWidth,imageHeight,imageChannel);
    }
    else{
        LOGD("数据长宽高通道不匹配，直接返回空");
        LOGD("数据宽=%d,高=%d,通道=%d",imageWidth,imageHeight,imageChannel);
        return NULL;
    }

    jbyte *imageDate = env->GetByteArrayElements(imageDate_, NULL);
    if (NULL == imageDate){
        LOGD("导入数据为空，直接返回空");
        env->ReleaseByteArrayElements(imageDate_, imageDate, 0);
        return NULL;
    }

    if(imageWidth<20||imageHeight<20){
        LOGD("导入数据的宽和高小于20，直接返回空");
        env->ReleaseByteArrayElements(imageDate_, imageDate, 0);
        return NULL;
    }

    //TODO 通道需测试
    if(3 == imageChannel || 4 == imageChannel){
        //图像通道数只能是3或4；
    }else{
        LOGD("图像通道数只能是3或4，直接返回空");
        env->ReleaseByteArrayElements(imageDate_, imageDate, 0);
        return NULL;
    }

    //int32_t minFaceSize=40;
    //mtcnn->SetMinFace(minFaceSize);

    unsigned char *ImageCharDate = (unsigned char*)imageDate;
    ncnn::Mat ncnn_img;
    int resSize = coor->GetInputImgSize();

    if(imageChannel==3) {
        ncnn_img = ncnn::Mat::from_pixels_resize(ImageCharDate, ncnn::Mat::PIXEL_BGR2RGB, imageWidth, imageHeight,resSize,resSize);
    }else{
        ncnn_img = ncnn::Mat::from_pixels_resize(ImageCharDate, ncnn::Mat::PIXEL_RGBA2RGB, imageWidth, imageHeight,resSize,resSize);
    }
    LOGD("w=%d,h=%d,c=%d",ncnn_img.w,ncnn_img.h,ncnn_img.c);
    std::vector<Object> objects;



    int res = coor->detect(ncnn_img,objects,imageWidth,imageHeight);


    int32_t num_oor = static_cast<int32_t>(objects.size());
    LOGD("检测到的海洋生物数目：%d\n", num_oor);

    int out_size = 1+num_oor*6;
    float *OorInfo = new float[out_size];
    OorInfo[0] =float(num_oor);
    for(int i=0;i<num_oor;i++){
        OorInfo[6*i+1] = objects[i].label;//left
        OorInfo[6*i+2] = objects[i].prob;//top
        OorInfo[6*i+3] = objects[i].rect.x;//right
        OorInfo[6*i+4] = objects[i].rect.y;
        OorInfo[6*i+5] = objects[i].rect.width;
        OorInfo[6*i+6] = objects[i].rect.height;

    }
    jfloatArray tOorInfo = env->NewFloatArray(out_size);
    env->SetFloatArrayRegion(tOorInfo,0,out_size,OorInfo);
    //  LOGD("内部人脸检测完成,导出数据成功");
    delete[] OorInfo;
    env->ReleaseByteArrayElements(imageDate_, imageDate, 0);
    return tOorInfo;
    //return 0;

}
extern "C" JNIEXPORT jboolean JNICALL
Java_bistu_grobot_oor_MainActivity_CoorModelUnInit(JNIEnv *env, jobject instance) {
    if(!detection_sdk_init_ok){
        LOGD("人脸检测MTCNN模型已经释放过或者未初始化");
        return true;
    }
    jboolean tDetectionUnInit = false;
    delete coor;


    detection_sdk_init_ok=false;
    tDetectionUnInit = true;
    LOGD("检测初始化锁，重新置零");
    return tDetectionUnInit;

}
extern "C" JNIEXPORT jboolean JNICALL
Java_bistu_grobot_oor_MainActivity_SetInputSize(JNIEnv *env, jobject instance,jint resSize){
    jboolean tRet = true;
    coor->SetInputSize(resSize);
    return tRet;

}
extern "C" JNIEXPORT jint JNICALL
Java_bistu_grobot_oor_MainActivity_GetInputImgSize(JNIEnv *env, jobject instance)
{

    return coor->GetInputImgSize();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_bistu_grobot_oor_MainActivity_SetNumThreads(JNIEnv *env, jobject instance,jint numThreads)
{
    jboolean tRet = true;

    coor->SetNumThreads(numThreads);
    return tRet;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_bistu_grobot_oor_MainActivity_SetTimeCount(JNIEnv *env, jobject instance,jint timeCount)
{
    jboolean tRet = true;

    coor->SetTimeCount(timeCount);
    return tRet;
}

